#include "LecteurSymbole.h"
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <stdlib.h> // pour exit
using namespace std;

/*
 - Cette classe nous permet de lire une chaine de notre fichier et de la mettre dans un objet de la classe Symbole
et de lui affecté une catgorie grace au constructeur de ce dernier objet
 - pour que tout ce déroule bien on a ignorer les séparateur et les commentaires
 */


////////////////////////////////////////////////////////////////////////////////
//COnstructeur de la Classe LecteurSymbole ( construction pas composition du membre de la classe symCour par une chaine vide => catégorie <FINDEFICHIER>
// plus construction par composition du membre lc qui est un objet de la classe LecteurCaractere avec le nom du fichier à lire
LecteurSymbole::LecteurSymbole(string nomFich) : lc(nomFich), symCour("") {
    suivant(); // pour lire le premier symbole du fichier (toujour lire un objet en avance)
}


////////////////////////////////////////////////////////////////////////////////
// permet d'enregisté dans l'objet this la ligne et la colonne du symbole a lire ainsi que de lire le nouveau symbole 
//et lc contient le premier caractere du symbole suivant
void LecteurSymbole::suivant() {  
    
    while( sauterSeparateurs() || sauterCommentaires() ){ } 
    // cette boucle nous permet de sauter tous les commentaires et ceparateurs 
    // on la mis ici pour pouvoir avoire la bonne ligne et colonne du premier caractére du symbole
    
    // on est maintenant positionne sur le premier caractère d'un symbole
    ligne = lc.getLigne();
    colonne = lc.getColonne();
    symCour = Symbole(motSuivant()); // symCour contient le symbole courant du fichier et lc contien le premier caractere du prochain symbole
}


////////////////////////////////////////////////////////////////////////////////
// Permet de lire un mot et de se positionner sur le suivant (axactement le caracter su suivant (toujour lire un objet en avance) )
string LecteurSymbole::motSuivant() {  
    static string s;
    s = "";
    
    //--------------------------------
    if (isdigit(lc.getCarCour()))  // c'est le début d'un entier  (ou un mot clé)
        do {
            s = s + lc.getCarCour();
            lc.suivant();
        } while (isdigit(lc.getCarCour())); // quand je sort de la boucle l'objet lc contient le caractére suivant du fichier
        
    //--------------------------------
    else if (isalpha(lc.getCarCour())) // c'est le début d'un mot  ( ou d'un mot clé)
        do {
            s = s + lc.getCarCour();
            lc.suivant();
        } while (isalpha(lc.getCarCour()) || isdigit(lc.getCarCour()) || lc.getCarCour() == '_'); // quand je sort de la boucle l'objet lc contient le caractére suivant du fichier
        
    //--------------------------------   
    else if (lc.getCarCour()=='"') { // c'est le début d'une chaine 
        do{
            s=s+lc.getCarCour();
            lc.suivant();
        }while( lc.getCarCour()!='"'  &&  lc.getCarCour()!=EOF );
        if (lc.getCarCour()==EOF) exit(0); // j'ai pas de " pour montré la fin de la chaine => Erreur qu'on va résoudre aprés avec une exception 
        else s=s+lc.getCarCour(); lc.suivant(); // La lecture de la chaine c'est bien terminer :)
      }  // quand je sort de la boucle l'objet lc contient le caractére suivant du fichier
    //--------------------------------
    else if (lc.getCarCour()=='=' || lc.getCarCour()=='!' || lc.getCarCour()=='<'|| lc.getCarCour()=='>') {   //c'est le début d'un opérateur binaire.
        
        s=s+lc.getCarCour();
        lc.suivant();
        
        if (lc.getCarCour()=='=') {
                s=s+lc.getCarCour();
                lc.suivant();
        }
    }
      
    //--------------------------------
    else if (lc.getCarCour() != EOF) // c'est un caractere special (ou un mot clé)
    {
        s = lc.getCarCour();
        lc.suivant();
    } // quand je sort de la boucle l'objet lc contient le caractére suivant du fichier

    //--------------------------------
    return s; // ( peut retourner EOF si pas les 4 cas => rest dans l'état initiale (déclaration voir ci-dessus))
}

///////////////////////////////////////////////////////////////////////////////
// on test s'il ya un commentaire , s'il ya un on le lit jusqu'a la fin de la ligne pour l'ignoré puis on lit le premier caractére de la ligne suivante 
// si plusieurs ligne on commentaire on reboucle pour les ignoré toutes
bool LecteurSymbole::sauterCommentaires(){
    bool commentaire=false;
        do{
                if (lc.getCarCour()=='#') // teste si c'est le debut d'un commentaire
                {
                     commentaire=true;
                     do{
                          lc.suivant();
                     }while(lc.getCarCour() !='\n' ); // teste si fin du commentaire
                     lc.suivant(); // lecture du premier caractére de la ligne suivante pour testé si c'est un nouveau commentaire
                }
         }while(lc.getCarCour()=='#'); // si le premier caractére de la ligne suivante est aussi un # => debut de commentaire
     // quand je sort de la boucle l'objet lc contient le caractére suivant du fichier
    return commentaire;
}

////////////////////////////////////////////////////////////////////////////////
 // je peux comparé dé le debut puisque dans le constructeur du lecteur de caracter jai lu le premier du fichier
bool LecteurSymbole::sauterSeparateurs() {
    bool separateur=false;
        while (lc.getCarCour() == ' ' || lc.getCarCour() == '\t' || lc.getCarCour() == '\r' || lc.getCarCour() == '\n')
        { 
                lc.suivant(); 
                separateur=true; 
        }
    // quand je sort de la boucle l'objet lc contient le caractére suivant du fichier
    return separateur;
}
